using ColorFillGame.Application.Commands;
using ColorFillGame.Domain.Entities;
using ColorFillGame.Domain.Exceptions;
using ColorFillGame.Domain.Repositories;
using ColorFillGame.Domain.ValueObjects;
using MediatR;

namespace ColorFillGame.Application.Commands;

public class SetPlayerColorCommandHandler : IRequestHandler<SetPlayerColorCommand>
{
    private readonly IGameRepository _gameRepository;
    private readonly IPlayerRepository _playerRepository;

    public SetPlayerColorCommandHandler(
        IGameRepository gameRepository,
        IPlayerRepository playerRepository)
    {
        _gameRepository = gameRepository;
        _playerRepository = playerRepository;
    }

    public async Task Handle(SetPlayerColorCommand request, CancellationToken cancellationToken)
    {
        // 获取游戏
        var game = await _gameRepository.GetByIdAsync(request.GameId);
        if (game == null)
            throw new GameNotFoundException(request.GameId);

        // 获取玩家
        var player = await _playerRepository.GetByIdAsync(request.PlayerId);
        if (player == null)
            throw new PlayerNotFoundException(request.PlayerId);

        // 检查玩家是否属于该游戏
        if (player.GameId != request.GameId)
            throw new DomainException("Player does not belong to this game.");

        // 尝试从十六进制代码获取颜色名称
        // 首先获取所有可用颜色
        var availableColors = PlayerColor.GetAvailableColors();
        
        // 查找对应的颜色名称
        string? colorName = null;
        foreach (var name in availableColors)
        {
            var color = PlayerColor.FromName(name);
            if (color.HexCode.Equals(request.HexColor, StringComparison.OrdinalIgnoreCase))
            {
                colorName = name;
                break;
            }
        }

        if (colorName == null)
            throw new DomainException($"Invalid color code: {request.HexColor}");

        // 检查这个颜色是否已经被其他玩家使用
        var usedColors = game.Players
            .Where(p => p.Id != player.Id && p.Color != null)
            .Select(p => p.Color.Name)
            .ToList();

        if (usedColors.Contains(colorName))
            throw new DomainException($"Color {colorName} is already used by another player");

        // 设置玩家颜色
        player.SetColor(PlayerColor.FromName(colorName));
        await _playerRepository.UpdateAsync(player);
        await _playerRepository.SaveChangesAsync();
    }
}